//==========================================================================
// Copyright (c) 2000-2006,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#ifndef _PEIMAGE_H_
#define _PEIMAGE_H_

#define UNALIGNED

//
// Define the linker version number.  This is temporary to aid
// in debugging with people trying to load images built with
// an older linker.  This is not required in the final product.
//

#define IMAGE_MAJOR_LINKER_VERSION 2

//
// Image Format
//

// BUG: gcc arm
#if defined(_x86) || defined(_EVC)
#pragma pack(1)
#endif // _x86

#if defined(_MSC_VER) || defined(_EVC)
#define DECLSPEC_SELECTANY      __declspec(selectany)
#define DECLSPEC_NOVTABLE       __declspec(novtable)
#define DECLSPEC_UUID(x)        __declspec(uuid(x))
#define DECL_NAKED              __declspec(naked)
#define DECL_PACKED
#define DECL_SECTION(s)
#elif defined(_GNUC)
#define DECL_REGPARM(n)         __attribute__ ((regparm(n)))
#define DECL_SECTION(s)         __attribute__ ((section(s)))
#define DECL_PACKED             __attribute__ ((packed))
#define DECL_ALIGN(n)           __attribute__ ((aligned(n)))
#define DECL_NORETURN           __attribute__ ((noreturn))
#define DECL_NAKED
#endif // defined(_MSC_VER)


typedef char                CHAR;
typedef short               SHORT;
typedef int                 INT;
typedef long                LONG;
typedef void                VOID;
typedef unsigned long       SIZE_T;

typedef unsigned char       UCHAR;
typedef unsigned short      USHORT;
typedef unsigned int        UINT;
typedef unsigned long       ULONG;

typedef Aura_Int8           INT8;
typedef Aura_Int16          INT16;
typedef Aura_Int32          INT32;
typedef Aura_Int64          INT64;

typedef Aura_UInt8          UINT8;
typedef Aura_UInt16         UINT16;
typedef Aura_UInt32         UINT32;
typedef Aura_UInt64         UINT64;

typedef INT                 BOOL;
typedef UINT8               BYTE;
typedef Aura_WChar             WCHAR;

typedef void               *HANDLE;
typedef void               *PVOID;
typedef LONG                LRESULT;

typedef VOID        *LPVOID;
typedef const void*  LPCVOID;
typedef CHAR        *PCHAR,  *LPCHAR;
typedef UCHAR       *PUCHAR, *LPUCHAR;
typedef WCHAR       *PWCHAR, *LPWCHAR;
typedef Aura_WChar     *PTSTR,  *LPTSTR;
typedef Aura_UInt32       *PULONG;
typedef USHORT      *PUSHORT;

typedef CHAR        *PSTR,   *LPSTR;
typedef WCHAR       *PWSTR,  *LPWSTR;
typedef const CHAR  *PCSTR,  *LPCSTR;
typedef const WCHAR *PCWSTR, *LPCWSTR;
typedef const Aura_WChar        *LPCTSTR;

typedef long LONG_PTR, *PLONG_PTR;

typedef unsigned short  WORD;
typedef unsigned long   DWORD;
typedef DWORD          *PDWORD;
typedef const void     *PCVOID;

typedef DWORD          *LPDWORD;


#define IMAGE_DOS_SIGNATURE                 0x5A4D      // MZ
#define IMAGE_NT_SIGNATURE                  0x00004550  // PE00

typedef struct DECL_PACKED _IMAGE_DOS_HEADER {      // DOS .EXE header
    USHORT uhMagic;
    USHORT uhLastPageSize;
    USHORT uhTotalPages;
    USHORT uhRelocations;
    USHORT uhHeaderSize;
    USHORT uhMinAlloc;
    USHORT uhMaxAlloc;
    USHORT uhSS;
    USHORT uhSP;
    USHORT uhChecksum;
    USHORT uhIP;
    USHORT uhCS;
    USHORT uhRelocationTableOffset;
    USHORT uhOverlayNumber;
    USHORT ahReserved[4];
    USHORT uhOEMId;
    USHORT uhOEMInfo;
    USHORT ahReserved2[10];
    LONG   lNewHeaderOffset;
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

//
// File header format.
//

typedef struct DECL_PACKED _IMAGE_FILE_HEADER {
    USHORT  uhMachine;
    USHORT  uhNumberOfSections;
    ULONG   ulTimeDateStamp;
    ULONG   ulPointerToSymbolTable;
    ULONG   ulNumberOfSymbols;
    USHORT  uhSizeOfOptionalHeader;
    USHORT  uhCharacteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

#define IMAGE_SIZEOF_FILE_HEADER            20

// Relocation info stripped from file.
#define IMAGE_FILE_RELOCS_STRIPPED          0x0001

// File is executable  (i.e. no unresolved externel references).
#define IMAGE_FILE_EXECUTABLE_IMAGE         0x0002

// Line nunbers stripped from file.
#define IMAGE_FILE_LINE_NUMS_STRIPPED       0x0004

// Local symbols stripped from file.
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED      0x0008

#define IMAGE_FILE_MINIMAL_OBJECT           0x0010  // Reserved.
#define IMAGE_FILE_UPDATE_OBJECT            0x0020  // Reserved.
#define IMAGE_FILE_16BIT_MACHINE            0x0040  // 16 bit word machine.

// Bytes of machine word are reversed.
#define IMAGE_FILE_BYTES_REVERSED_LO        0x0080

#define IMAGE_FILE_32BIT_MACHINE            0x0100  // 32 bit word machine.

// Debugging info stripped from file in .DBG file
#define IMAGE_FILE_DEBUG_STRIPPED           0x0200

#define IMAGE_FILE_PATCH                    0x0400  // Reserved.
#define IMAGE_FILE_SYSTEM                   0x1000  // System File.
#define IMAGE_FILE_DLL                      0x2000  // File is a DLL.

// Bytes of machine word are reversed.
#define IMAGE_FILE_BYTES_REVERSED_HI        0x8000

#define IMAGE_FILE_MACHINE_UNKNOWN          0
#define IMAGE_FILE_MACHINE_I860             0x14d   // Intel 860.
#define IMAGE_FILE_MACHINE_I386             0x14c   // Intel 386.

// MIPS little-endian, 0540 big-endian
#define IMAGE_FILE_MACHINE_R3000            0x162

#define IMAGE_FILE_MACHINE_R4000            0x166   // MIPS little-endian
#define IMAGE_FILE_MACHINE_ALPHA            0x184   // Alpha_AXP
#define IMAGE_FILE_MACHINE_ARM              0x1c0   // Arm 7

//
// Directory format.
//

typedef struct DECL_PACKED _IMAGE_DATA_DIRECTORY {
    ULONG   ulVirtualAddress;
    ULONG   ulSize;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES    16

//
// Optional header format.
//

typedef struct DECL_PACKED _IMAGE_OPTIONAL_HEADER {
    //
    // Standard fields.
    //

    USHORT  uhMagic;
    UCHAR   ucMajorLinkerVersion;
    UCHAR   ucMinorLinkerVersion;
    ULONG   ulSizeOfCode;
    ULONG   ulSizeOfInitializedData;
    ULONG   ulSizeOfUninitializedData;
    ULONG   ulAddressOfEntryPoint;
    ULONG   ulBaseOfCode;
    ULONG   ulBaseOfData;

    //
    // NT additional fields.
    //

    ULONG   ulImageBase;
    ULONG   ulSectionAlignment;
    ULONG   ulFileAlignment;
    USHORT  uhMajorOperatingSystemVersion;
    USHORT  uhMinorOperatingSystemVersion;
    USHORT  uhMajorImageVersion;
    USHORT  uhMinorImageVersion;
    USHORT  uhMajorSubsystemVersion;
    USHORT  uhMinorSubsystemVersion;
    ULONG   ulReserved1;
    ULONG   ulSizeOfImage;
    ULONG   ulSizeOfHeaders;
    ULONG   ulCheckSum;
    USHORT  uhSubsystem;
    USHORT  uhDllCharacteristics;
    ULONG   ulSizeOfStackReserve;
    ULONG   ulSizeOfStackCommit;
    ULONG   ulSizeOfHeapReserve;
    ULONG   ulSizeOfHeapCommit;
    ULONG   ulLoaderFlags;
    ULONG   ulNumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY aDataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;

#define IMAGE_SIZEOF_STD_OPTIONAL_HEADER      28
#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER      224

typedef struct DECL_PACKED _IMAGE_NT_HEADERS {
    ULONG ulSignature;
    IMAGE_FILE_HEADER fileHeader;
    IMAGE_OPTIONAL_HEADER optionalHeader;
} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;

#define IMAGE_FIRST_SECTION(ntheader) ((PIMAGE_SECTION_HEADER)        \
    ((ULONG)ntheader +                                                  \
     FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) +                 \
     ((PIMAGE_NT_HEADERS)(ntheader))->fileHeader.SizeOfOptionalHeader   \
    ))


// Subsystem Values

#define IMAGE_SUBSYSTEM_UNKNOWN              0   // Unknown subsystem.

// Image doesn't require a subsystem.
#define IMAGE_SUBSYSTEM_NATIVE               1

// Image runs in the Windows GUI subsystem.
#define IMAGE_SUBSYSTEM_WINDOWS_GUI          2

// Image runs in the Windows character subsystem.
#define IMAGE_SUBSYSTEM_WINDOWS_CUI          3

// image runs in the OS/2 character subsystem.
#define IMAGE_SUBSYSTEM_OS2_CUI              5

// image run  in the Posix character subsystem.
#define IMAGE_SUBSYSTEM_POSIX_CUI            7

// Dll Characteristics

// Dll has a process initialization routine.
#define IMAGE_LIBRARY_PROCESS_INIT           1

// Dll has a thread termination routine.
#define IMAGE_LIBRARY_PROCESS_TERM           2

// Dll has a thread initialization routine.
#define IMAGE_LIBRARY_THREAD_INIT            4

// Dll has a thread termination routine.
#define IMAGE_LIBRARY_THREAD_TERM            8

//
// Loader Flags
//

#define IMAGE_LOADER_FLAGS_BREAK_ON_LOAD    0x00000001
#define IMAGE_LOADER_FLAGS_DEBUG_ON_LOAD    0x00000002


// Directory Entries

#define IMAGE_DIRECTORY_ENTRY_EXPORT         0   // Export Directory
#define IMAGE_DIRECTORY_ENTRY_IMPORT         1   // Import Directory
#define IMAGE_DIRECTORY_ENTRY_RESOURCE       2   // Resource Directory
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION      3   // Exception Directory
#define IMAGE_DIRECTORY_ENTRY_SECURITY       4   // Security Directory
#define IMAGE_DIRECTORY_ENTRY_BASERELOC      5   // Base Relocation Table
#define IMAGE_DIRECTORY_ENTRY_DEBUG          6   // Debug Directory
#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT      7   // Description String
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR      8   // Machine Value (MIPS GP)
#define IMAGE_DIRECTORY_ENTRY_TLS            9   // TLS Directory
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG   10   // Load Configuration Directory
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT  11   // Bound Import Directory
#define IMAGE_DIRECTORY_ENTRY_IAT           12   // Import Aura_Address Table

//
// Section header format.
//

#define IMAGE_SIZEOF_SHORT_NAME              8

typedef struct DECL_PACKED _IMAGE_SECTION_HEADER {
    UCHAR   szName[IMAGE_SIZEOF_SHORT_NAME];
    union {
            ULONG   ulPhysicalAddress;
            ULONG   ulVirtualSize;
    } misc;
    ULONG   ulVirtualAddress;
    ULONG   ulSizeOfRawData;
    ULONG   ulPointerToRawData;
    ULONG   ulPointerToRelocations;
    ULONG   ulPointerToLinenumbers;
    USHORT  uhNumberOfRelocations;
    USHORT  uhNumberOfLinenumbers;
    ULONG   ulCharacteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

#define IMAGE_SIZEOF_SECTION_HEADER          40

#define IMAGE_SCN_TYPE_REGULAR               0x00000000  //
#define IMAGE_SCN_TYPE_DUMMY                 0x00000001  // Reserved.
#define IMAGE_SCN_TYPE_NO_LOAD               0x00000002  // Reserved.

// Used for 16-bit offset code.
#define IMAGE_SCN_TYPE_GROUPED               0x00000004

#define IMAGE_SCN_TYPE_NO_PAD                0x00000008  // Reserved.
#define IMAGE_SCN_TYPE_COPY                  0x00000010  // Reserved.

// Section contains code.
#define IMAGE_SCN_CNT_CODE                   0x00000020

// Section contains initialized data.
#define IMAGE_SCN_CNT_INITIALIZED_DATA       0x00000040

// Section contains uninitialized data.
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA     0x00000080

#define IMAGE_SCN_LNK_OTHER                  0x00000100  // Reserved.
// Section contains comments or some other type of information.

#define IMAGE_SCN_LNK_INFO                   0x00000200
// Section contains an overlay.

#define IMAGE_SCN_LNK_OVERLAY                0x00000400

// Section contents will not become part of image.
#define IMAGE_SCN_LNK_REMOVE                 0x00000800

// Section contents comdat.
#define IMAGE_SCN_LNK_COMDAT                 0x00001000

#define IMAGE_SCN_ALIGN_1BYTES               0x00100000
#define IMAGE_SCN_ALIGN_2BYTES               0x00200000
#define IMAGE_SCN_ALIGN_4BYTES               0x00300000
#define IMAGE_SCN_ALIGN_8BYTES               0x00400000

// Default alignment if no others are specified.
#define IMAGE_SCN_ALIGN_16BYTES              0x00500000

#define IMAGE_SCN_ALIGN_32BYTES              0x00600000
#define IMAGE_SCN_ALIGN_64BYTES              0x00700000

// Section can be discarded.
#define IMAGE_SCN_MEM_DISCARDABLE            0x02000000

// Section is not cachable.
#define IMAGE_SCN_MEM_NOT_CACHED             0x04000000

// Section is not pageable.
#define IMAGE_SCN_MEM_NOT_PAGED              0x08000000

// Section is shareable.
#define IMAGE_SCN_MEM_SHARED                 0x10000000

// Section is executable.
#define IMAGE_SCN_MEM_EXECUTE                0x20000000

// Section is readable.
#define IMAGE_SCN_MEM_READ                   0x40000000

// Section is writeable.
#define IMAGE_SCN_MEM_WRITE                  0x80000000

//
// Symbol format.
//

typedef struct DECL_PACKED _IMAGE_SYMBOL {
    union {
        UCHAR   szShortName[8];
        struct {
            ULONG   ulShort;     // if 0, use LongName
            ULONG   ulLong;      // offset into string table
        } Name;
        PUCHAR  apLongName[2];
    } N;
    ULONG   ulValue;
    SHORT   hSectionNumber;
    USHORT  uhType;
    UCHAR   ucStorageClass;
    UCHAR   ucNumberOfAuxSymbols;
} IMAGE_SYMBOL;

typedef IMAGE_SYMBOL UNALIGNED *PIMAGE_SYMBOL;

#define IMAGE_SIZEOF_SYMBOL                  18

//
// Section values.
//
// Symbols have a section number of the section in which they are
// defined. Otherwise, section numbers have the following meanings:
//

// Symbol is undefined or is common.
#define IMAGE_SYM_UNDEFINED           (SHORT)0

// Symbol is an absolute value.
#define IMAGE_SYM_ABSOLUTE            (SHORT)-1

// Symbol is a special debug item.
#define IMAGE_SYM_DEBUG               (SHORT)-2

//
// Type (fundamental) values.
//

#define IMAGE_SYM_TYPE_NULL                  0  // no type.
#define IMAGE_SYM_TYPE_VOID                  1
#define IMAGE_SYM_TYPE_CHAR                  2  // type character.
#define IMAGE_SYM_TYPE_SHORT                 3  // type short integer.
#define IMAGE_SYM_TYPE_INT                   4
#define IMAGE_SYM_TYPE_LONG                  5
#define IMAGE_SYM_TYPE_FLOAT                 6
#define IMAGE_SYM_TYPE_DOUBLE                7
#define IMAGE_SYM_TYPE_STRUCT                8
#define IMAGE_SYM_TYPE_UNION                 9
#define IMAGE_SYM_TYPE_ENUM                  10 // enumeration.
#define IMAGE_SYM_TYPE_MOE                   11 // member of enumeration.
#define IMAGE_SYM_TYPE_UCHAR                 12
#define IMAGE_SYM_TYPE_USHORT                13
#define IMAGE_SYM_TYPE_UINT                  14
#define IMAGE_SYM_TYPE_ULONG                 15

//
// Type (derived) values.
//

#define IMAGE_SYM_DTYPE_NULL                 0  // no derived type.
#define IMAGE_SYM_DTYPE_POINTER              1  // pointer.
#define IMAGE_SYM_DTYPE_FUNCTION             2  // function.
#define IMAGE_SYM_DTYPE_ARRAY                3  // array.

//
// Storage classes.
//

#define IMAGE_SYM_CLASS_END_OF_FUNCTION      (UCHAR)-1
#define IMAGE_SYM_CLASS_NULL                 0
#define IMAGE_SYM_CLASS_AUTOMATIC            1
#define IMAGE_SYM_CLASS_EXTERNAL             2
#define IMAGE_SYM_CLASS_STATIC               3
#define IMAGE_SYM_CLASS_REGISTER             4
#define IMAGE_SYM_CLASS_EXTERNAL_DEF         5
#define IMAGE_SYM_CLASS_LABEL                6
#define IMAGE_SYM_CLASS_UNDEFINED_LABEL      7
#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT     8
#define IMAGE_SYM_CLASS_ARGUMENT             9
#define IMAGE_SYM_CLASS_STRUCT_TAG           10
#define IMAGE_SYM_CLASS_MEMBER_OF_UNION      11
#define IMAGE_SYM_CLASS_UNION_TAG            12
#define IMAGE_SYM_CLASS_TYPE_DEFINITION      13
#define IMAGE_SYM_CLASS_UNDEFINED_STATIC     14
#define IMAGE_SYM_CLASS_ENUM_TAG             15
#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM       16
#define IMAGE_SYM_CLASS_REGISTER_PARAM       17
#define IMAGE_SYM_CLASS_BIT_FIELD            18
#define IMAGE_SYM_CLASS_BLOCK                100
#define IMAGE_SYM_CLASS_FUNCTION             101
#define IMAGE_SYM_CLASS_END_OF_STRUCT        102
#define IMAGE_SYM_CLASS_FILE                 103
#define IMAGE_SYM_CLASS_SECTION              104
#define IMAGE_SYM_CLASS_WEAK_EXTERNAL        105

// type packing constants

#define N_BTMASK                            017
#define N_TMASK                             060
#define N_TMASK1                            0300
#define N_TMASK2                            0360
#define N_BTSHFT                            4
#define N_TSHIFT                            2

// MACROS

// Basic Type of  x
#define BTYPE(x) ((x) & N_BTMASK)

// Is x a pointer ?
#ifndef ISPTR
#define ISPTR(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_POINTER << N_BTSHFT))
#endif

// Is x a function ?
#ifndef ISFCN
#define ISFCN(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_FUNCTION << N_BTSHFT))
#endif

// Is x an array ?

#ifndef ISARY
#define ISARY(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_ARRAY << N_BTSHFT))
#endif

// Is x a structure, union, or enumeration TAG ?
#ifndef ISTAG
#define ISTAG(x) ((x)==IMAGE_SYM_CLASS_STRUCT_TAG || \
                  (x)==IMAGE_SYM_CLASS_UNION_TAG || \
                  (x)==IMAGE_SYM_CLASS_ENUM_TAG)
#endif

#ifndef INCREF
#define INCREF(x) ((((x)&~N_BTMASK)<<N_TSHIFT) | \
                   (IMAGE_SYM_DTYPE_POINTER<<N_BTSHFT)|((x)&N_BTMASK))
#endif

#ifndef DECREF
#define DECREF(x) ((((x)>>N_TSHIFT)&~N_BTMASK)|((x)&N_BTMASK))
#endif

//
// Auxiliary entry format.
//

typedef union DECL_PACKED _IMAGE_AUX_SYMBOL {
    struct {
        ULONG    ulTagIndex;          // struct, union, or enum tag index
        union {
            struct {
                USHORT  uhLinenumber; // declaration line number
                USHORT  uhSize;       // size of struct, union, or enum
            } LnSz;
           ULONG    ulTotalSize;
        } dMisc;
        union {
            struct {                            // if ISFCN, tag, or .bb
                ULONG    ulPointerToLinenumber;
                ULONG    ulPointerToNextFunction;
            } dFunction;
            struct {                            // if ISARY, up to 4 dimen.
                USHORT   ahDimension[4];
            } dArray;
        } dFcnAry;
        USHORT  uhTvIndex;                        // tv index
    } sym;
    struct {
        UCHAR   acName[IMAGE_SIZEOF_SYMBOL];
    } file;
    struct {
        ULONG   ulLength;                 // section length
        USHORT  uhNumberOfRelocations;    // number of relocation entries
        USHORT  uhNumberOfLinenumbers;    // number of line numbers
        ULONG   ulCheckSum;               // checksum for communal
        SHORT   hNumber;                  // section number to associate with
        UCHAR   ucSelection;              // communal selection type
    } section;
} IMAGE_AUX_SYMBOL;

typedef IMAGE_AUX_SYMBOL UNALIGNED *PIMAGE_AUX_SYMBOL;

#define IMAGE_SIZEOF_AUX_SYMBOL              18

//
// Communal selection types.
//

#define IMAGE_COMDAT_SELECT_UNKNOWN        0
#define IMAGE_COMDAT_SELECT_NODUPLICATES   1
#define IMAGE_COMDAT_SELECT_ANY            2
#define IMAGE_COMDAT_SELECT_SAME_SIZE      3
#define IMAGE_COMDAT_SELECT_EXACT_MATCH    4
#define IMAGE_COMDAT_SELECT_ASSOCIATIVE    5

#define IMAGE_WEAK_EXTERN_SEARCH_UNKNOWN   0
#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1
#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY   2


//
// Relocation format.
//

typedef struct _IMAGE_RELOCATION {
    ULONG   ulVirtualAddress;
    ULONG   ulSymbolTableIndex;
    USHORT  uhType;
} IMAGE_RELOCATION;
typedef IMAGE_RELOCATION UNALIGNED *PIMAGE_RELOCATION;

#define IMAGE_SIZEOF_RELOCATION              10

//
// I860 relocation types.
//

// Reference is absolute, no relocation is necessary
#define IMAGE_REL_I860_ABSOLUTE              0

// Direct 32-bit reference to the symbols virtual address
#define IMAGE_REL_I860_DIR32                 06

#define IMAGE_REL_I860_DIR32NB               07
#define IMAGE_REL_I860_SECTION               012
#define IMAGE_REL_I860_SECREL                013
#define IMAGE_REL_I860_PAIR                  034
#define IMAGE_REL_I860_HIGH                  036
#define IMAGE_REL_I860_LOW0                  037
#define IMAGE_REL_I860_LOW1                  040
#define IMAGE_REL_I860_LOW2                  041
#define IMAGE_REL_I860_LOW3                  042
#define IMAGE_REL_I860_LOW4                  043
#define IMAGE_REL_I860_SPLIT0                044
#define IMAGE_REL_I860_SPLIT1                045
#define IMAGE_REL_I860_SPLIT2                046
#define IMAGE_REL_I860_HIGHADJ               047
#define IMAGE_REL_I860_BRADDR                050

//
// I386 relocation types.
//

// Reference is absolute, no relocation is necessary
#define IMAGE_REL_I386_ABSOLUTE              0

// Direct 16-bit reference to the symbols virtual address
#define IMAGE_REL_I386_DIR16                 01

// PC-relative 16-bit reference to the symbols virtual address
#define IMAGE_REL_I386_REL16                 02

// Direct 32-bit reference to the symbols virtual address
#define IMAGE_REL_I386_DIR32                 06

// Direct 32-bit reference to the symbols virtual address, base not included
#define IMAGE_REL_I386_DIR32NB               07

// Direct 16-bit reference to the segment-selector bits of a 32-bit vir-addr
#define IMAGE_REL_I386_SEG12                 011

#define IMAGE_REL_I386_SECTION               012
#define IMAGE_REL_I386_SECREL                013

// PC-relative 32-bit reference to the symbols virtual address
#define IMAGE_REL_I386_REL32                 024

//
// MIPS relocation types.
//

// Reference is absolute, no relocation is necessary
#define IMAGE_REL_MIPS_ABSOLUTE              0

#define IMAGE_REL_MIPS_REFHALF               01
#define IMAGE_REL_MIPS_REFWORD               02
#define IMAGE_REL_MIPS_JMPADDR               03
#define IMAGE_REL_MIPS_REFHI                 04
#define IMAGE_REL_MIPS_REFLO                 05
#define IMAGE_REL_MIPS_GPREL                 06
#define IMAGE_REL_MIPS_LITERAL               07
#define IMAGE_REL_MIPS_SECTION               012
#define IMAGE_REL_MIPS_SECREL                013
#define IMAGE_REL_MIPS_REFWORDNB             042
#define IMAGE_REL_MIPS_PAIR                  045

//
// Alpha Relocation types.
//

#define IMAGE_REL_ALPHA_ABSOLUTE             0x0
#define IMAGE_REL_ALPHA_REFLONG              0x1
#define IMAGE_REL_ALPHA_REFQUAD              0x2
#define IMAGE_REL_ALPHA_GPREL32              0x3
#define IMAGE_REL_ALPHA_LITERAL              0x4
#define IMAGE_REL_ALPHA_LITUSE               0x5
#define IMAGE_REL_ALPHA_GPDISP               0x6
#define IMAGE_REL_ALPHA_BRADDR               0x7
#define IMAGE_REL_ALPHA_HINT                 0x8
#define IMAGE_REL_ALPHA_INLINE_REFLONG       0x9
#define IMAGE_REL_ALPHA_REFHI                0xA
#define IMAGE_REL_ALPHA_REFLO                0xB
#define IMAGE_REL_ALPHA_PAIR                 0xC
#define IMAGE_REL_ALPHA_MATCH                0xD
#define IMAGE_REL_ALPHA_SECTION              0xE
#define IMAGE_REL_ALPHA_SECREL               0xF
#define IMAGE_REL_ALPHA_REFLONGNB            0x10

//
// Based relocation format.
//

typedef struct DECL_PACKED _IMAGE_BASE_RELOCATION {
    ULONG   ulVirtualAddress;
    ULONG   ulSizeOfBlock;
    USHORT  ahTypeOffset[1];
} IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION;

#define IMAGE_SIZEOF_BASE_RELOCATION         8

//
// Based relocation types.
//

#define IMAGE_REL_BASED_ABSOLUTE              0
#define IMAGE_REL_BASED_HIGH                  1
#define IMAGE_REL_BASED_LOW                   2
#define IMAGE_REL_BASED_HIGHLOW               3
#define IMAGE_REL_BASED_HIGHADJ               4
#define IMAGE_REL_BASED_MIPS_JMPADDR          5
#define IMAGE_REL_BASED_I860_BRADDR           6
#define IMAGE_REL_BASED_I860_SPLIT            7

//
// Line number format.
//

typedef struct DECL_PACKED _IMAGE_LINENUMBER {
    union {
        // Symbol table index of function name if Linenumber is 0.
        ULONG   ulSymbolTableIndex;

        ULONG   ulVirtualAddress;   // Virtual address of line number.
    } dType;
    USHORT  uhLinenumber;           // Line number.
} IMAGE_LINENUMBER;

typedef IMAGE_LINENUMBER UNALIGNED *PIMAGE_LINENUMBER;

#define IMAGE_SIZEOF_LINENUMBER              6

//
// Archive format.
//

#define IMAGE_ARCHIVE_START_SIZE             8
#define IMAGE_ARCHIVE_START                  "!<arch>\n"
#define IMAGE_ARCHIVE_END                    "`\n"
#define IMAGE_ARCHIVE_PAD                    "\n"
#define IMAGE_ARCHIVE_LINKER_MEMBER          "/               "
#define IMAGE_ARCHIVE_LONGNAMES_MEMBER       "//              "

typedef struct DECL_PACKED _IMAGE_ARCHIVE_MEMBER_HEADER {
    UCHAR    acName[16];     // File member name - `/' terminated.
    UCHAR    acDate[12];     // File member date - decimal.
    UCHAR    acUserID[6];    // File member user id - decimal.
    UCHAR    acGroupID[6];   // File member group id - decimal.
    UCHAR    acMode[8];      // File member mode - octal.
    UCHAR    acSize[10];     // File member size - decimal.
    UCHAR    acEndHeader[2]; // String to end header.
} IMAGE_ARCHIVE_MEMBER_HEADER, *PIMAGE_ARCHIVE_MEMBER_HEADER;

#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR      60

//
// DLL support.
//

//
// Export Format
//

typedef struct DECL_PACKED _IMAGE_EXPORT_DIRECTORY {
    ULONG   ulCharacteristics;
    ULONG   ulTimeDateStamp;
    USHORT  uhMajorVersion;
    USHORT  uhMinorVersion;
    ULONG   ulName;
    ULONG   ulBase;
    ULONG   ulNumberOfFunctions;
    ULONG   ulNumberOfNames;
    PULONG  *plAddressOfFunctions;
    PULONG  *plAddressOfNames;
    PUSHORT phAddressOfNameOrdinals;
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

//
// Import Format
//

typedef struct DECL_PACKED _IMAGE_IMPORT_BY_NAME {
    USHORT  uhHint;
    UCHAR   acName[1];
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

typedef struct DECL_PACKED _IMAGE_THUNK_DATA {
    union {
        PULONG plFunction;
        ULONG ulOrdinal;
        PIMAGE_IMPORT_BY_NAME pAddressOfData;
    } u1;
} IMAGE_THUNK_DATA, *PIMAGE_THUNK_DATA;

#define IMAGE_ORDINAL_FLAG 0x80000000
#define IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG) != 0)
#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)

typedef struct DECL_PACKED _IMAGE_IMPORT_DESCRIPTOR {
    union {
        ULONG   ulCharacteristics;
        ULONG   ulOriginalFirstThunk;
    };
    ULONG   ulTimeDateStamp;
    ULONG   ulForwarderChain;
    ULONG   ulName;
    PIMAGE_THUNK_DATA pFirstThunk;
} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR;

//
// Thread Local Storage
//

/*
typedef void
(MODENTRY *PIMAGE_TLS_CALLBACK) (
    PTR pDllHandle,
    ULONG ulReason,
    PTR pReserved
    );
*/

typedef void
(__stdcall *PIMAGE_TLS_CALLBACK) (
    Aura_UInt32* pDllHandle,
    ULONG ulReason,
    Aura_UInt32* pReserved
    );

typedef struct DECL_PACKED _IMAGE_TLS_DIRECTORY {
    ULONG   ulStartAddressOfRawData;
    ULONG   ulEndAddressOfRawData;
    PULONG  plAddressOfIndex;
    PIMAGE_TLS_CALLBACK *pAddressOfCallBacks;
    ULONG   ulSizeOfZeroFill;
    ULONG   ulCharacteristics;
} IMAGE_TLS_DIRECTORY, *PIMAGE_TLS_DIRECTORY;


//
// Resource Format.
//

//
// Resource directory consists of two counts, following by a variable length
// array of directory entries.  The first count is the number of entries at
// beginning of the array that have actual names associated with each entry.
// The entries are in ascending order, case insensitive strings.  The second
// count is the number of entries that immediately follow the named entries.
// This second count identifies the number of entries that have 31-bit integer
// Ids as their name.  These entries are also sorted in ascending order.
//
// This structure allows fast lookup by either name or number, but for any
// given resource entry only one form of lookup is supported, not both.
// This is consistant with the syntax of the .RC file and the .RES file.
//

typedef struct DECL_PACKED _IMAGE_RESOURCE_DIRECTORY {
    ULONG   ulCharacteristics;
    ULONG   ulTimeDateStamp;
    USHORT  uhMajorVersion;
    USHORT  uhMinorVersion;
    USHORT  uhNumberOfNamedEntries;
    USHORT  uhNumberOfIdEntries;
//  IMAGE_RESOURCE_DIRECTORY_ENTRY aDirectoryEntries[];
} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;

#define IMAGE_RESOURCE_NAME_IS_STRING        0x80000000
#define IMAGE_RESOURCE_DATA_IS_DIRECTORY     0x80000000

//
// Each directory contains the 32-bit Name of the entry and an offset,
// relative to the beginning of the resource directory of the data associated
// with this directory entry.  If the name of the entry is an actual text
// string instead of an integer Id, then the high order bit of the name field
// is set to one and the low order 31-bits are an offset, relative to the
// beginning of the resource directory of the string, which is of type
// IMAGE_RESOURCE_DIRECTORY_STRING.  Otherwise the high bit is clear and the
// low-order 31-bits are the integer Id that identify this resource directory
// entry. If the directory entry is yet another resource directory (i.e. a
// subdirectory), then the high order bit of the offset field will be
// set to indicate this.  Otherwise the high bit is clear and the offset
// field points to a resource data entry.
//

typedef struct DECL_PACKED _IMAGE_RESOURCE_DIRECTORY_ENTRY {
    union {
        struct {
            ULONG ulNameOffset:31;
            ULONG ulNameIsString:1;
        };
        ULONG   ulName;
        USHORT  uhId;
    };
    union {
        ULONG   ulOffsetToData;
        struct {
            ULONG   ulOffsetToDirectory:31;
            ULONG   ulDataIsDirectory:1;
        };
    };
} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;

//
// For resource directory entries that have actual string names, the Name
// field of the directory entry points to an object of the following type.
// All of these string objects are stored together after the last resource
// directory entry and before the first resource data object.  This minimizes
// the impact of these variable length objects on the alignment of the fixed
// size directory entry objects.
//

typedef struct DECL_PACKED _IMAGE_RESOURCE_DIRECTORY_STRING {
    USHORT  uhLength;
    Aura_WChar wszNameString[1];
} IMAGE_RESOURCE_DIRECTORY_STRING, *PIMAGE_RESOURCE_DIRECTORY_STRING;


//
// Each resource data entry describes a leaf node in the resource directory
// tree.  It contains an offset, relative to the beginning of the resource
// directory of the data for the resource, a size field that gives the number
// of bytes of data at that offset, a CodePage that should be used when
// decoding code point values within the resource data.  Typically for new
// applications the code page would be the unicode code page.
//

typedef struct DECL_PACKED _IMAGE_RESOURCE_DATA_ENTRY {
    ULONG   ulOffsetToData;
    ULONG   ulSize;
    ULONG   ulCodePage;
    ULONG   ulReserved;
} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY;

//
// Load Configuration Directory Entry
//

typedef struct DECL_PACKED _IMAGE_LOAD_CONFIG_DIRECTORY {
    ULONG   ulCharacteristics;
    ULONG   ulTimeDateStamp;
    USHORT  uhMajorVersion;
    USHORT  uhMinorVersion;
    ULONG   ulGlobalFlagsClear;
    ULONG   ulGlobalFlagsSet;
    ULONG   ulCriticalSectionDefaultTimeout;
    ULONG   ulDeCommitFreeBlockThreshold;
    ULONG   ulDeCommitTotalFreeThreshold;
    ULONG   alReserved[8];
} IMAGE_LOAD_CONFIG_DIRECTORY, *PIMAGE_LOAD_CONFIG_DIRECTORY;


//
// Function table entry format for MIPS/ALPHA images.  Function table is
// pointed to by the IMAGE_DIRECTORY_ENTRY_EXCEPTION directory entry.
// This definition duplicates ones in ntmips.h and ntalpha.h for use
// by portable image file mungers.
//

typedef struct DECL_PACKED _IMAGE_RUNTIME_FUNCTION_ENTRY {
    ULONG ulBeginAddress;
    ULONG ulEndAddress;
/*
    PTR pExceptionHandler;
    PTR pHandlerData;
*/
    Aura_UInt32* pExceptionHandler;
    Aura_UInt32* pHandlerData;
    ULONG ulPrologEndAddress;
} IMAGE_RUNTIME_FUNCTION_ENTRY, *PIMAGE_RUNTIME_FUNCTION_ENTRY;

//
// Debug Format
//

typedef struct DECL_PACKED _IMAGE_DEBUG_DIRECTORY {
    ULONG   ulCharacteristics;
    ULONG   ulTimeDateStamp;
    USHORT  uhMajorVersion;
    USHORT  uhMinorVersion;
    ULONG   ulType;
    ULONG   ulSizeOfData;
    ULONG   ulAddressOfRawData;
    ULONG   ulPointerToRawData;
} IMAGE_DEBUG_DIRECTORY, *PIMAGE_DEBUG_DIRECTORY;

#define IMAGE_DEBUG_TYPE_UNKNOWN          0
#define IMAGE_DEBUG_TYPE_COFF             1
#define IMAGE_DEBUG_TYPE_CODEVIEW         2
#define IMAGE_DEBUG_TYPE_FPO              3
#define IMAGE_DEBUG_TYPE_MISC             4
#define IMAGE_DEBUG_TYPE_EXCEPTION        5
#define IMAGE_DEBUG_TYPE_FIXUP            6
#define IMAGE_DEBUG_TYPE_RESERVED6        7
#define IMAGE_DEBUG_TYPE_RESERVED7        8

typedef struct DECL_PACKED _IMAGE_COFF_SYMBOLS_HEADER {
    ULONG   ulNumberOfSymbols;
    ULONG   ulLvaToFirstSymbol;
    ULONG   ulNumberOfLinenumbers;
    ULONG   ulLvaToFirstLinenumber;
    ULONG   ulRvaToFirstByteOfCode;
    ULONG   ulRvaToLastByteOfCode;
    ULONG   ulRvaToFirstByteOfData;
    ULONG   ulRvaToLastByteOfData;
} IMAGE_COFF_SYMBOLS_HEADER, *PIMAGE_COFF_SYMBOLS_HEADER;

#define FRAME_FPO   0
#define FRAME_TRAP  1
#define FRAME_TSS   2

#ifndef _GNUC
#pragma warning(disable:4214)
#endif // !_GNUC

typedef struct DECL_PACKED _FPO_DATA {
    ULONG       ulOffStart;          // offset 1st byte of function code
    ULONG       ulProcSize;          // # bytes in function
    ULONG       ulLocals;            // # bytes in locals/4
    USHORT      uhParams;            // # bytes in params/4
    USHORT      bbProlog   : 8;      // # bytes in prolog
    USHORT      bbRegs     : 3;      // # regs saved
    USHORT      bbHasSEH   : 1;      // AURA_TRUE if SEH in func
    USHORT      bbUseBP    : 1;      // AURA_TRUE if EBP has been allocated
    USHORT      bbReserved : 1;      // reserved for future use
    USHORT      bbFrame    : 2;      // frame type
} FPO_DATA, *PFPO_DATA;
#define SIZEOF_RFPO_DATA 16

#ifndef _GNUC
#pragma warning(default:4214)
#endif // !_GNUC

#define IMAGE_DEBUG_MISC_EXENAME    1

typedef struct DECL_PACKED _IMAGE_DEBUG_MISC {
    ULONG       ulDataType;       // type of misc data, see defines
    ULONG       ulLength;         // total length of record, rounded to four
                                              // byte multiple.
    UCHAR       ucUnicode;        // AURA_TRUE if data is unicode string
    UCHAR       acReserved[3];
    UCHAR       acData[1];        // Actual data
} IMAGE_DEBUG_MISC, *PIMAGE_DEBUG_MISC;


//
// Debugging information can be stripped from an image file and placed
// in a separate .DBG file, whose file name part is the same as the
// image file name part (e.g. symbols for CMD.EXE could be stripped
// and placed in CMD.DBG).  This is indicated by the IMAGE_FILE_DEBUG_STRIPPED
// flag in the Characteristics field of the file header.  The beginning of
// the .DBG file contains the following structure which captures certain
// information from the image file.  This allows a debug to proceed even if
// the original image file is not accessable.  This header is followed by
// zero of more IMAGE_SECTION_HEADER structures, followed by zero or more
// IMAGE_DEBUG_DIRECTORY structures.  The latter structures and those in
// the image file contain file offsets relative to the beginning of the
// .DBG file.
//
// If symbols have been stripped from an image, the IMAGE_DEBUG_MISC structure
// is left in the image file, but not mapped.  This allows a debugger to
// compute the name of the .DBG file, from the name of the image in the
// IMAGE_DEBUG_MISC structure.
//

typedef struct DECL_PACKED _IMAGE_SEPARATE_DEBUG_HEADER {
    USHORT      uhSignature;
    USHORT      uhFlags;
    USHORT      uhMachine;
    USHORT      uhCharacteristics;
    ULONG       ulTimeDateStamp;
    ULONG       ulCheckSum;
    ULONG       ulImageBase;
    ULONG       ulSizeOfImage;
    ULONG       ulNumberOfSections;
    ULONG       ulExportedNamesSize;
    ULONG       ulDebugDirectorySize;
    ULONG       alReserved[3];
} IMAGE_SEPARATE_DEBUG_HEADER, *PIMAGE_SEPARATE_DEBUG_HEADER;

#define IMAGE_SEPARATE_DEBUG_SIGNATURE 0x4944

// BUG: gcc arm
#if defined(_x86) || defined(_EVC)
#pragma pack()
#endif // _x86

//
// End Image Format
//

#endif // _PEIMAGE_H_
